'Compute the sanitized gradients.
Args:
loss: the loss tensor.
var_list: the optional variables.
add_noise: if true, then add noise. Always clip.
Returns:
a pair of (list of sanitized gradients) and privacy spending accumulation
operations.
Raises:
TypeError: if var_list contains non-variable.'

def compute_sanitized_gradients(self, loss, var_list=None, add_noise=True):

    self._assert_valid_dtypes([loss])
    xs = [tf.convert_to_tensor(x) for x in var_list]
    px_grads = per_example_gradients.PerExampleGradients(loss, xs)
    sanitized_grads = []
    for (px_grad, v) in zip(px_grads, var_list):
        tensor_name = utils.GetTensorOpName(v)
        sanitized_grad = self._sanitizer.sanitize(px_grad, self._eps_delta, sigma=self._sigma, tensor_name=tensor_name, add_noise=add_noise, num_examples=(self._batches_per_lot * tf.slice(tf.shape(px_grad), [0], [1])))
        sanitized_grads.append(sanitized_grad)
    return sanitized_grads
