code: def var_descriptor(obj, _prev_obs=None, _tag_generator=None):
      """
      Returns a string, with no endlines, fully specifying
      how a variable is computed. Does not include any memory
      location dependent information such as the id of a node.
      """
      if _prev_obs is None:
          _prev_obs = {}
  
      if id(obj) in _prev_obs:
          tag = _prev_obs[id(obj)]
  
          return "<" + tag + ">"
  
      if _tag_generator is None:
          _tag_generator = _TagGenerator()
  
      cur_tag = _tag_generator.get_tag()
  
      _prev_obs[id(obj)] = cur_tag
  
      if hasattr(obj, "__array__"):
          # hashlib hashes only the contents of the buffer, but
          # it can have different semantics depending on the strides
          # of the ndarray
          name = "<ndarray:"
          name += (
              "strides=["
              + ",".join(str(stride) for stride in obj.strides)
              + "]"
          )
          name += ",digest=" + hashlib.sha256(obj).hexdigest() + ">"
      elif hasattr(obj, "owner") and obj.owner is not None:
          name = str(obj.owner.op) + "("
          name += ",".join(
              var_descriptor(
                  ipt,
                  _prev_obs=_prev_obs,
                  _tag_generator=_tag_generator,
              )
              for ipt in obj.owner.inputs
          )
          name += ")"
      elif hasattr(obj, "name") and obj.name is not None:
          # Only print the name if there is no owner.
          # This way adding a name to an intermediate node can't make
          # a deeper graph get the same descriptor as a shallower one
          name = obj.name
      else:
          name = str(obj)
          if " at 0x" in name:
              # The __str__ method is encoding the object's id in its str
              name = position_independent_str(obj)
              if " at 0x" in name:
                  print(name)
                  assert False
  
      prefix = cur_tag + "="
  
      rval = prefix + name
  
      return rval
  
imports: from __future__ import absolute_import, print_function, division
  from copy import copy
  import logging
  import os
  import sys
  import hashlib
  import numpy
  from six import string_types, integer_types, iteritems
  from six.moves import StringIO, reduce
  import theano
  from theano import gof
  from theano import config
  from theano.gof import Op, Apply
  from theano.compile import Function, debugmode, SharedVariable
label_desc: Use image node_id 5 for calling a global function with example usage: var_descriptor(obj, _prev_obs, _tag_generator) and returns: rval, unknown