Compute the accuracy of a TF Eager model on some data
  :param model: instance of cleverhans.model.Model_Eager
                  with pretrained weights for evaluation.
  :param X_test: numpy array with training inputs
  :param Y_test: numpy array with training outputs
  :param args: dict or argparse `Namespace` object.
               Should contain `batch_size`
  :param attack: instance of the class cleverhans.attacks.attacks_eager
  :param attack_args: parameters required for the attack.
  :return: a float with the accuracy value

def model_eval(model, X_test=None, Y_test=None, args=None,
               attack=None, attack_args=None):
  """
  Compute the accuracy of a TF Eager model on some data
  :param model: instance of cleverhans.model.Model_Eager
                  with pretrained weights for evaluation.
  :param X_test: numpy array with training inputs
  :param Y_test: numpy array with training outputs
  :param args: dict or argparse `Namespace` object.
               Should contain `batch_size`
  :param attack: instance of the class cleverhans.attacks.attacks_eager
  :param attack_args: parameters required for the attack.
  :return: a float with the accuracy value
  """
  args = _ArgsWrapper(args or {})

  if ((attack is None) != (attack_args is None)):
    raise ValueError("attack and attack_args must be "
                     "passed together.")
  assert args.batch_size, "Batch size was not given in args dict"
  if X_test is None or Y_test is None:
    raise ValueError("X_test argument and Y_test argument "
                     "must be supplied.")

  # Init result var
  accuracy = 0.0

  # Compute number of batches
  nb_batches = int(math.ceil(float(len(X_test)) / args.batch_size))
  assert nb_batches * args.batch_size >= len(X_test)

  X_cur = np.zeros((args.batch_size,) + X_test.shape[1:],
                   dtype=X_test.dtype)
  Y_cur = np.zeros((args.batch_size,) + Y_test.shape[1:],
                   dtype=Y_test.dtype)

  tfe = tf.contrib.eager
  batch_x = tfe.Variable(X_test[0:args.batch_size], dtype=tf.float32)
  batch_y = tfe.Variable(Y_test[0:args.batch_size], dtype=tf.float32)
  for batch in range(nb_batches):
    if batch % 100 == 0 and batch > 0:
      _logger.debug("Batch " + str(batch))

    # Must not use the `batch_indices` function here, because it
    # repeats some examples.
    # It's acceptable to repeat during training, but not eval.
    start = batch * args.batch_size
    end = min(len(X_test), start + args.batch_size)

    # The last batch may be smaller than all others. This should not
    # affect the accuarcy disproportionately.
    cur_batch_size = end - start
    X_cur[:cur_batch_size] = X_test[start:end]
    Y_cur[:cur_batch_size] = Y_test[start:end]
    tf.assign(batch_x, X_cur)
    tf.assign(batch_y, Y_cur)
    if attack is not None:
      batch_adv_x = attack.generate(batch_x, **attack_args)
      predictions = model.get_probs(batch_adv_x)
    else:
      predictions = model.get_probs(batch_x)
    cur_corr_preds = tf.equal(tf.argmax(batch_y, axis=-1),
                              tf.argmax(predictions, axis=-1))

    accuracy += cur_corr_preds.numpy()[:cur_batch_size].sum()

  assert end >= len(X_test)

  # Divide by number of examples to get final value
  accuracy /= len(X_test)

  return accuracy