'Adapted from Tensorflow Optimizer base class member function.
Add operations to minimize `loss` by updating `var_list`.
This method simply combines calls `compute_gradients()` and
`apply_gradients()`. If you want to process the gradient before applying
them call `tf.gradients()` and `self.apply_gradients()` explicitly instead
of using this function.
Args:
loss: A Tensor containing the value to minimize.
global_step: Optional Variable to increment by one after the variables
have been updated.
var_list: Optional list or tuple of Variable objects to update to
minimize loss. Defaults to the list of variables collected in
the graph under the key GraphKeys.TRAINABLE_VARIABLES.
gate_gradients: How to gate the computation of gradients.
Can be GATE_NONE, GATE_OP, or GATE_GRAPH.
aggregation_method: Specifies the method used to combine gradient terms.
Valid values are defined in the class AggregationMethod.
colocate_gradients_with_ops: If True, try colocating gradients with
the corresponding op.
name: Optional name for the returned operation.
grad_loss: Optional. A Tensor holding the gradient computed for loss.
Returns:
An Operation that updates the variables in var_list.
If global_step was not None, that operation also increments global_step.
Raises:
ValueError: if no gradients are provided for any variable.'

def minimize(self, loss, global_step=None, var_list=None, gate_gradients=GATE_OP, aggregation_method=None, colocate_gradients_with_ops=False, name=None, grad_loss=None):

    grads_and_vars = self._optimizer.compute_gradients(loss, var_list=var_list, gate_gradients=gate_gradients, aggregation_method=aggregation_method, colocate_gradients_with_ops=colocate_gradients_with_ops, grad_loss=grad_loss)
    vars_with_grad = [v for (g, v) in grads_and_vars if (g is not None)]
    if (not vars_with_grad):
        raise ValueError(('No    gradients    provided    for    any    variable,    check    your    graph    for    ops    that    do    not    support    gradients,    between    variables    %s    and    loss    %s.' % ([str(v) for (_, v) in grads_and_vars], loss)))
    for (g, v) in grads_and_vars:
        print('g    ', g)
        print('v    ', v)
    return self.apply_gradients(grads_and_vars, global_step=global_step)
