message: Add basic Tensorflow eager micro benchmark.
  In addition, implemented ParameterizedBenchmark class so that we no longer have
  to write benchamrk functions for all the configuration matrix.  For example,
  tensorflow/python/eager/benchmarks_test.py is very bloated due to this.
diff: @@ -23,6 +23,7 @@ import os
  import re
  import sys
  import time
  +import types
  import six
  @@ -51,6 +52,30 @@ TEST_REPORTER_TEST_ENV = "TEST_REPORT_FILE_PREFIX"
  OVERRIDE_GLOBAL_THREADPOOL = "TF_OVERRIDE_GLOBAL_THREADPOOL"
  +def _rename_function(f, arg_num, name):
  + """Rename the given function's name appears in the stack trace."""
  + func_code = six.get_function_code(f)
  + if six.PY2:
  + new_code = types.CodeType(arg_num, func_code.co_nlocals,
  + func_code.co_stacksize, func_code.co_flags,
  + func_code.co_code, func_code.co_consts,
  + func_code.co_names, func_code.co_varnames,
  + func_code.co_filename, name,
  + func_code.co_firstlineno, func_code.co_lnotab,
  + func_code.co_freevars, func_code.co_cellvars)
  + else:
  + new_code = types.CodeType(arg_num, 0, func_code.co_nlocals,
  + func_code.co_stacksize, func_code.co_flags,
  + func_code.co_code, func_code.co_consts,
  + func_code.co_names, func_code.co_varnames,
  + func_code.co_filename, name,
  + func_code.co_firstlineno, func_code.co_lnotab,
  + func_code.co_freevars, func_code.co_cellvars)
  +
  + return types.FunctionType(new_code, f.__globals__, name, f.__defaults__,
  + f.__closure__)
  +
  +
  def _global_report_benchmark(
  name, iters=None, cpu_time=None, wall_time=None,
  throughput=None, extras=None, metrics=None):
  @@ -136,13 +161,44 @@ class _BenchmarkRegistrar(type):
  """The Benchmark class registrar. Used by abstract Benchmark class."""
  def __new__(mcs, clsname, base, attrs):
  - newclass = super(mcs, _BenchmarkRegistrar).__new__(
  - mcs, clsname, base, attrs)
  + newclass = type.__new__(mcs, clsname, base, attrs)
  if not newclass.is_abstract():
  GLOBAL_BENCHMARK_REGISTRY.add(newclass)
  return newclass
  +class ParameterizedBenchmark(_BenchmarkRegistrar):
  + """Metaclass to generate parameterized benchmarks."""
  +
  + def __new__(mcs, clsname, base, attrs):
  + param_config_list = attrs["_benchmark_parameters"]
  +
  + for name in attrs.copy().keys():
  + if not name.startswith("benchmark"):
  + continue
  +
  + original_benchmark = attrs[name]
  + del attrs[name]
  +
  + for param_config in param_config_list:
  + test_name_suffix = param_config[0]
  + params = param_config[1:]
  + benchmark_name = name + "__" + test_name_suffix
  + if benchmark_name in attrs:
  + raise Exception(
  + "Benchmark named {} already defined.".format(benchmark_name))
  +
  + def create_benchmark_function(params):
  + return lambda self: original_benchmark(self, *params)
  +
  + benchmark = create_benchmark_function(params)
  + # Renaming is important because `report_benchmark` function looks up the
  + # function name in the stack trace.
  + attrs[benchmark_name] = _rename_function(benchmark, 1, benchmark_name)
  +
  + return super(mcs, ParameterizedBenchmark).__new__(mcs, clsname, base, attrs)
  +
  +
  class Benchmark(six.with_metaclass(_BenchmarkRegistrar, object)):
  """Abstract class that provides helper functions for running benchmarks.
  