message: Cache name of op in ops.py
  This method can be surprisingly slow, due to the string formatting it performs. By caching the result, we save ~2s on our graph building benchmark:
  Before:
  tottime  cumtime
  1.140    2.505    ops.py:2088(name)
  After:
  tottime  cumtime
  0.204    0.520    ops.py:2091(name)
diff: @@ -332,6 +332,7 @@ class Tensor(_TensorLike):
  # to easily navigate a computation graph.
  self._consumers = []
  self._id = uid()
  + self._name = None
  @property
  def op(self):
  @@ -351,9 +352,11 @@ class Tensor(_TensorLike):
  @property
  def name(self):
  """The string name of this tensor."""
  + if self._name is None:
  if not self._op.name:
  raise ValueError("Operation was not named: %s" % self._op)
  - return "%s:%d" % (self._op.name, self._value_index)
  + self._name = "%s:%d" % (self._op.name, self._value_index)
  + return self._name
  @property
  def device(self):
  