'Construct a differentially private gradient descent optimizer.
The optimizer uses fixed privacy budget for each batch of training.
Args:
learning_rate: for GradientDescentOptimizer.
eps_delta: EpsDelta pair for each epoch.
sanitizer: for sanitizing the graident.
sigma: noise sigma. If None, use eps_delta pair to compute sigma;
otherwise use supplied sigma directly.
use_locking: use locking.
name: name for the object.
batches_per_lot: Number of batches in a lot.'

def __init__(self, learning_rate, eps_delta, sanitizer, sigma=None, use_locking=False, name='DPGradientDescent', batches_per_lot=1):

    super(DPGradientDescentOptimizer, self).__init__(learning_rate, use_locking, name)
    self._batches_per_lot = batches_per_lot
    self._grad_accum_dict = {}
    if (batches_per_lot > 1):
        self._batch_count = tf.Variable(1, dtype=tf.int32, trainable=False, name='batch_count')
        var_list = tf.trainable_variables()
        with tf.variable_scope('grad_acc_for'):
            for var in var_list:
                v_grad_accum = tf.Variable(tf.zeros_like(var), trainable=False, name=utils.GetTensorOpName(var))
                self._grad_accum_dict[var.name] = v_grad_accum
    self._eps_delta = eps_delta
    self._sanitizer = sanitizer
    self._sigma = sigma
