**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
"""@property: list of tasks directly upstream"""
        return [self.dag.get_task(tid) for tid in self._upstream_task_ids]
    @property
    def upstream_task_ids(self) -> Set[str]:
        """@property: set of ids of tasks directly upstream"""
        return self._upstream_task_ids
    @property
    def downstream_list(self) -> List["BaseOperator"]:
        """@property: list of tasks directly downstream"""
        return [self.dag.get_task(tid) for tid in self._downstream_task_ids]
    @property
    def downstream_task_ids(self) -> Set[str]:
        """@property: set of ids of tasks directly downstream"""
        return self._downstream_task_ids
    @provide_session
    def clear(self,