'Sanitize the given tensor.
This santize a given tensor by first applying l2 norm clipping and then
adding Gaussian noise. It calls the privacy accountant for updating the
privacy spending.
Args:
x: the tensor to sanitize.
eps_delta: a pair of eps, delta for (eps,delta)-DP. Use it to
compute sigma if sigma is None.
sigma: if sigma is not None, use sigma.
option: a ClipOption which, if supplied, used for
clipping and adding noise.
tensor_name: the name of the tensor.
num_examples: if None, use the number of "rows" of x.
add_noise: if True, then add noise, else just clip.
Returns:
a pair of sanitized tensor and the operation to accumulate privacy
spending.'

def sanitize(self, x, eps_delta, sigma=None, option=ClipOption(None, None), tensor_name=None, num_examples=None, add_noise=True):

    if (sigma is None):
        (eps, delta) = eps_delta
        with tf.control_dependencies([tf.Assert(tf.greater(eps, 0), ['eps    needs    to    be    greater    than    0']), tf.Assert(tf.greater(delta, 0), ['delta    needs    to    be    greater    than    0'])]):
            sigma = (tf.sqrt((2.0 * tf.log((1.25 / delta)))) / eps)
    (l2norm_bound, clip) = option
    if (l2norm_bound is None):
        (l2norm_bound, clip) = self._default_option
        if ((tensor_name is not None) and (tensor_name in self._options)):
            (l2norm_bound, clip) = self._options[tensor_name]
    if clip:
        x = utils.BatchClipByL2norm(x, l2norm_bound)
    if add_noise:
        if (num_examples is None):
            num_examples = tf.slice(tf.shape(x), [0], [1])
        privacy_accum_op = self._accountant.accumulate_privacy_spending(eps_delta, sigma, num_examples)
        with tf.control_dependencies([privacy_accum_op]):
            saned_x = utils.AddGaussianNoise(tf.reduce_sum(x, 0), (sigma * l2norm_bound))
    else:
        saned_x = tf.reduce_sum(x, 0)
    return saned_x
