'Args:
raw_grad_list: Ngpu x Nvar x 2 gradient list from all towers
ps_var_grads: Nvar x 2 (grad, ps_var)
Returns:
list of copy ops'

def _apply_gradients_and_copy(self, raw_grad_list, ps_var_grads):

    opt = self.model.get_optimizer()
    var_update_ops = []
    for (vid, (g, v)) in enumerate(ps_var_grads):
        apply_gradient_op = opt.apply_gradients([(g, v)])
        barrier = self._add_sync_queues_and_barrier('param_update_barrier_{}'.format(vid), [apply_gradient_op])
        with tf.control_dependencies([barrier]):
            with tf.device(self.cpu_device):
                updated_value = v.read_value()
                for towerid in range(self.nr_gpu):
                    var_update_ops.append(raw_grad_list[towerid][vid][1].assign(updated_value))
    return var_update_ops
