Helper method inserting compliance logging ops.

  Note: This helper is not guaranteed to be efficient, as it will insert ops
        and control dependencies. If this proves to be a bottleneck, submitters
        may wish to consider other methods such as extracting values from an
        .events file.

  Args:
    op: A tf op to be printed.
    log_id: a uuid provided by the logger in mlperf_log.py
    every_n: If repeat is True, with what frequency should the input op be '
             logged. If repeat is False, this argument is ignored.
    first_n: Only log this many values. This arg does not interact with every_n.
             The first_n refers to the first n that would have been logged.

def log_deferred(op, log_id, every_n=1, first_n=None):
  """Helper method inserting compliance logging ops.

  Note: This helper is not guaranteed to be efficient, as it will insert ops
        and control dependencies. If this proves to be a bottleneck, submitters
        may wish to consider other methods such as extracting values from an
        .events file.

  Args:
    op: A tf op to be printed.
    log_id: a uuid provided by the logger in mlperf_log.py
    every_n: If repeat is True, with what frequency should the input op be '
             logged. If repeat is False, this argument is ignored.
    first_n: Only log this many values. This arg does not interact with every_n.
             The first_n refers to the first n that would have been logged.
  """

  prefix = ":::MLPv0.5.0 [{}]".format(log_id)
  if not first_n is not None and first_n == 1:
    return tf.Print(op, [tf.timestamp(), op], message=prefix, first_n=1)

  counter = tf.Variable(tf.zeros(shape=(), dtype=tf.int32) - 1,
                        aggregation=tf.VariableAggregation.MEAN)
  increment = tf.assign_add(counter, 1, use_locking=True)
  return tf.cond(
      tf.equal(tf.mod(increment, every_n), 0),
      lambda :tf.Print(op, [tf.timestamp(), op], message=prefix,
                       first_n=first_n),
      lambda :op
  )