'Returns a scaling factor to apply to the gradients.
The scaling factor is computed such that the root mean squared
average of the scaled gradients across all layers will be less than
or equal to the provided clip_norm value. This factor is always <1, so
never scales up the gradients.
Arguments:
param_list (list): List of layer parameters
clip_norm (float, optional): Target norm for the gradients. If not provided
the returned scale_factor will equal 1.
Returns:
scale_factor (float): Computed scale factor.'

def clip_gradient_norm(self, param_list, clip_norm):

    scale_factor = 1
    if clip_norm:
        grad_list = [grad for ((param, grad), states) in param_list]
        grad_square_sums = sum((self.be.sum(self.be.square(grad)) for grad in grad_list))
        grad_norm = self.be.zeros((1, 1))
        grad_norm[:] = (self.be.sqrt(grad_square_sums) / self.be.bsz)
        scale_factor = (clip_norm / max(float(grad_norm.get()), float(clip_norm)))
    return scale_factor
