/// <summary>
            /// Creates a Tensor from an Abstraction.
            /// The difference with Elementwise.Create is that we reuse the existing arrays.
            /// </summary>
            private Tensor <Type> Lift(Scalar <Type> expr)
            {
                if (expr == this.Abstraction)
                {
                    return(this);
                }

                var result = Vars.FirstOrDefault(e => e == expr);

                if (result != null)
                {
                    return(Inputs[Array.IndexOf(Vars, expr)]);
                }

                // HACK: here the `Clone` only works on some specific cases.
                switch (expr)
                {
                case Scalar <Type> .Binary binary:
                    return(Op.Apply(Lift(binary.x), Lift(binary.y), (_x, _y) => binary.Clone(_x, _y)));

                case Scalar <Type> .Unary unary:
                    return(Op.Apply(Lift(unary.x), _x => unary.Clone(_x)));

                case Scalar <Type> .Const cst:
                    return(Op.ConstLike(expr, this));

                default:
                    throw new NotImplementedException();
                }
            }
            internal static Tensor <Type> Create(Tensor <Type> x, Func <Scalar <Type>, Scalar <Type> > f)
            {
                if (x is Fill <Type> )
                {
                    var fill = (Fill <Type>)x;
                    return(Op.ConstLike(f(fill.x), fill));
                }
                else
                {
                    var _x = new Scalar <Type> .Var($"_x{x0++}");

                    return(Create(new[] { x }, new[] { _x }, f(_x)));
                }
            }