**Description**

Currently `BaseOperator` and `XComArgs` implements the same logic of `__lshift__`, `__rshift__` and others "chain" operations (`>>`, `<<`). It seems resonable to abstract this logic into `TaskMixin` to introduce some DRYness especially because the new concept of `TaskGroup` will also implement the same methods.

**Use case / motivation**

Limit duplication of logic.

**Related Issues**

https://github.com/apache/airflow/pull/10827#issuecomment-691927501
#10153 

airflow/models/baseoperator.py
"""
    Base metaclass of BaseOperator.
    """
    def __call__(cls, *args, **kwargs):
        """
        Called when you call BaseOperator(). In this way we are able to perform an action
        after initializing an operator no matter where  the ``super().__init__`` is called
        (before or after assign of new attributes in a custom operator).
        """
        obj: BaseOperator = type.__call__(cls, *args, **kwargs)
        
        obj.set_xcomargs_dependencies()
        
        obj._BaseOperator__instantiated = True
        return obj
@functools.total_ordering
class BaseOperator(Operator, LoggingMixin, metaclass=BaseOperatorMeta):
    """
    Abstract base class for all operators. Since operators create objects that
    become nodes in the dag, BaseOperator contains many recursive methods for
    dag crawling behavior. To derive this class, you are expected to override
    the constructor as well as the 'execute' method.
    Operators derived from this class should perform or trigger certain tasks
    synchronously (wait for completion). Example of operators could be an
    operator that runs a Pig job (PigOperator), a sensor operator that
    waits for a partition to land in Hive (HiveSensorOperator), or one that
    moves data from Hive to MySQL (Hive2MySqlOperator). Instances of these
    operators (tasks) target specific operations, running specific scripts,
    functions or data transfers.