code: def safe_new(x, tag="", dtype=None):
      """
      Internal function that constructs a new variable from x with the same
      type, but with a different name (old name + tag). This function is used
      by gradient, or the R-op to construct new variables for the inputs of
      the inner graph such that there is no interference between the original
      graph and the newly constructed graph.
  
      """
      if hasattr(x, "name") and x.name is not None:
          nw_name = x.name + tag
      else:
          nw_name = None
  
      if isinstance(x, theano.Constant):
          if dtype and x.dtype != dtype:
              casted_x = x.astype(dtype)
              nwx = x.__class__(casted_x.type, x.data, x.name)
              nwx.tag = copy.copy(x.tag)
              return nwx
          else:
              return x.clone()
      # Note, as_tensor_variable will convert the Scalar into a
      # TensorScalar that will require a ScalarFromTensor op,
      # making the pushout optimization fail
      elif isinstance(x, scalar.ScalarVariable):
          if dtype:
              nw_x = scalar.get_scalar_type(dtype=dtype)()
          else:
              nw_x = x.type()
          nw_x.name = nw_name
          if theano.config.compute_test_value != "off":
              # Copy test value, cast it if necessary
              try:
                  x_test_value = gof.op.get_test_value(x)
              except AttributeError:
                  # There is no test value
                  pass
              else:
                  # This clause is executed if no exception was raised
                  nw_x.tag.test_value = nw_x.type.filter(x_test_value)
          return nw_x
      else:
          try:
              x = tensor.as_tensor_variable(x)
          except TypeError:
              # This could happen for example for random states
              pass
  
      # Cast x if needed. If x has a test value, this will also cast it.
      if dtype and x.dtype != dtype:
          x = x.astype(dtype)
  
      nw_x = x.type()
      nw_x.name = nw_name
      # Preserve test values so that the 'compute_test_value' option can be used.
      # The test value is deep-copied to ensure there can be no interactions
      # between test values, due to inplace operations for instance. This may
      # not be the most efficient memory-wise, though.
      if theano.config.compute_test_value != "off":
          try:
              nw_x.tag.test_value = copy.deepcopy(
                  gof.op.get_test_value(x)
              )
          except AttributeError:
              # This means `x` has no test value.
              pass
  
      return nw_x
  
imports: from __future__ import absolute_import, print_function, division
  import copy
  import logging
  import warnings
  from collections import OrderedDict
  import numpy
  import theano
  from theano.compat import izip
  from six import string_types, iteritems
  from six.moves import xrange
  from theano.compile.pfunc import rebuild_collect_shared
  from theano import gof, compat
  from theano import tensor, scalar
  from theano.tensor.basic import get_scalar_constant_value
label_desc: Use image node_id 1 for calling a global function with example usage: safe_new(x, tag, dtype) and returns: nw_x, nwx, x, nw_x