# Path: opt_einsum/sharing.py
# def to_backend_cache_wrap(to_backend: Any = None, constants: Any = False) -> Any:
#     """Decorates an ``to_backend()`` implementation to be memoized inside a
#     :func:`shared_intermediates` context (e.g. ``to_cupy``, ``to_torch``).
#     """
#     # manage the case that decorator is called with args
#     if to_backend is None:
#         return functools.partial(to_backend_cache_wrap, constants=constants)
# 
#     if constants:
# 
#         @functools.wraps(to_backend)
#         def cached_to_backend(array, constant=False):
#             if not currently_sharing():
#                 return to_backend(array, constant=constant)
# 
#             # hash by id
#             key = to_backend.__name__, id(array), constant
#             return _memoize(key, to_backend, array, constant=constant)
# 
#     else:
# 
#         @functools.wraps(to_backend)
#         def cached_to_backend(array):
#             if not currently_sharing():
#                 return to_backend(array)
# 
#             # hash by id
#             key = to_backend.__name__, id(array)
#             return _memoize(key, to_backend, array)
# 
#     return cached_to_backend


import numpy as np
        import tensorflow as tf
from ..sharing import to_backend_cache_wrap



__all__ = ["to_tensorflow", "build_expression", "evaluate_constants"]

_CACHED_TF_DEVICE = None


def _get_tensorflow_and_device():
    global _CACHED_TF_DEVICE

    if _CACHED_TF_DEVICE is None:

        try:
            eager = tf.executing_eagerly()
        except AttributeError:
            try:
                eager = tf.contrib.eager.in_eager_mode()
            except AttributeError:
                eager = False

        device = tf.test.gpu_device_name()
        if not device:
            device = "cpu"

        _CACHED_TF_DEVICE = tf, device, eager

    return _CACHED_TF_DEVICE



# Path: opt_einsum/sharing.py
# def to_backend_cache_wrap(to_backend: Any = None, constants: Any = False) -> Any:
#     """Decorates an ``to_backend()`` implementation to be memoized inside a
#     :func:`shared_intermediates` context (e.g. ``to_cupy``, ``to_torch``).
#     """
#     # manage the case that decorator is called with args
#     if to_backend is None:
#         return functools.partial(to_backend_cache_wrap, constants=constants)
# 
#     if constants:
# 
#         @functools.wraps(to_backend)
#         def cached_to_backend(array, constant=False):
#             if not currently_sharing():
#                 return to_backend(array, constant=constant)
# 
#             # hash by id
#             key = to_backend.__name__, id(array), constant
#             return _memoize(key, to_backend, array, constant=constant)
# 
#     else:
# 
#         @functools.wraps(to_backend)
#         def cached_to_backend(array):
#             if not currently_sharing():
#                 return to_backend(array)
# 
#             # hash by id
#             key = to_backend.__name__, id(array)
#             return _memoize(key, to_backend, array)
# 
#     return cached_to_backend


# Path: opt_einsum/backends/tensorflow.py
import numpy as np
        import tensorflow as tf
from ..sharing import to_backend_cache_wrap




__all__ = ["to_tensorflow", "build_expression", "evaluate_constants"]

_CACHED_TF_DEVICE = None


def _get_tensorflow_and_device():
    global _CACHED_TF_DEVICE

    if _CACHED_TF_DEVICE is None:

        try:
            eager = tf.executing_eagerly()
        except AttributeError:
            try:
                eager = tf.contrib.eager.in_eager_mode()
            except AttributeError:
                eager = False

        device = tf.test.gpu_device_name()
        if not device:
            device = "cpu"

        _CACHED_TF_DEVICE = tf, device, eager

    return _CACHED_TF_DEVICE



@to_backend_cache_wrap(constants=True)