Q:

Unity ball hitting paddle not reflecting right away

After the ball hits the paddle it continues for a frame or two in the physics, reflected direction, then my onCollisionEnter2D function runs and changes the velocity.  At least, that's what it seems like.  I'm a noob with Unity so I must be misunderstanding something. 
https://streamable.com/ac2gg
if (other.gameObject. CompareTag("Paddle"))
    {
        float dist = ballRb.transform.position.x - paddleRb.transform.position.x;

        if (dist > 0)
        {
            print("right");
            ballRb.velocity = new Vector2(4, speedY);
        }
        else
        {
            print("left");
            ballRb.velocity = new Vector2(-4, speedY);
        }
    }

Thoughts on why there's a stutter after a redirection?  I slowed it down so you can see better what's happening. 

A:

Great work on your code so far, it's not far off the solution. 
One issue you are having is the bounce is applied twice.  That is if it's positioned and timed right you'll bounce left and right. 
The other is physics is processing the bounce first which is off course from your fixed direction. 
Note: For correctness I must mention setting velocity isn't the recommended method, though certainly makes it easier, and with fixes below it works as intended.  This could be done by rotating a separate collider/rigidbody around a ray cast intersection to form the bounce surface invisible from the sprite, though that's another question. 
EDIT: I've added code for this at bottom of answer. 
Fixes

Add a boolean for rebounding while colliding
Check/set rebounding
Tick "is trigger" on the Paddle Collider (Remove physics)

While that may seem straight forward, there's more to it.  I took the liberty of writing an example:

public class BallVelocity : MonoBehaviour
{
    // Ref to rigidbody
    private Rigidbody2D m_BallRigidbody2D;

    // Ball Collider
    private Collider2D m_BallCollider;

    // Fixed Velocity on the Y axis to rebound with
    public float VelocityY = 4f;

    // Store these for use each fixed update
    private Vector3 m_NewVelocityLeft, m_NewVelocityRight;

    // Store if we have rebounded this collision
    private bool m_Rebounding = false;

    // need empty start for enable checkbox in editor
    private void Start()
    {

    }

    void Awake()
    {
        // Set references to require components
        m_BallRigidbody2D = GetComponent<Rigidbody2D>();
        m_BallCollider = GetComponent<Collider2D>();

        // Allocate once to prevent GC, however if values are to be calculated, move to FixedUpdate
        m_NewVelocityRight = new Vector2(4, VelocityY);
        m_NewVelocityLeft = new Vector2(-4, VelocityY);

        GetComponent<Rigidbody2D>().velocity = new Vector2(4, -VelocityY); ;
    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        // Manually check we have collided with paddle
        if (collision.gameObject.tag == "Paddle")
        {
            // Check we are not currently rebounding (still touching collider after last)
            if (! m_Rebounding)
            {
                m_Rebounding = true;

                float dist = transform.position.x - collision.transform.position.x;

                if (dist > 0)
                {
                    print("right");
                    // Set velocity once only in fixed update
                    // This is so other standard collisions will work, i.e. walls
                    m_BallRigidbody2D.velocity = m_NewVelocityRight;
                }
                else
                {
                    print("left");
                    m_BallRigidbody2D.velocity = m_NewVelocityLeft;
                }
            }
        }

    }

    private void OnTriggerExit2D(Collider2D collision)
    {
        if (collision.gameObject.tag == "Paddle")
        {
            // If not touching then we're clear of rebounding
            m_Rebounding = false;
        }
    }
}

Thrown together test:
https://streamable.com/d3iyn
To complete my answer with a method of rotating the paddle collider for the physics to process the bound I have created a project and Tutorial. 
Project on GitHub: https://github.com/Sibz/PaddleGame
Tutorial on YouTube: https://youtu.be/Vu0hSTDLuhk
And here's the code to go on the paddle.  However you need to set up the scene correctly. 

Set Preferences -> Physics2D -> Velocity Threshold to 0.0001 
Set Collider of paddle to be trigger, really thin and along top of
paddle.  
Put this paddle on it's own layer and set PaddleLayer 
Add a second 'invisible' Paddle with collider/rigidbody and set
PaddleCollider

public class Paddle : MonoBehaviour
{
    public GameObject Ball;
    public GameObject PaddleCollider;

    public float RayDistance = 1;

    public LayerMask PaddleLayer;

    [Tooltip("Max angle of paddle collider change when hitting the very end of the paddle.")] 
    [Range(1, 90)]
    public float AngularChange = 45;

    private Rigidbody2D m_BallRigidBody2D;
    private SpriteRenderer m_PaddleSpriteRenderer;
    private void Start()
    {
        m_BallRigidBody2D = Ball. GetComponent<Rigidbody2D>();
        m_PaddleSpriteRenderer = GetComponent<SpriteRenderer>();
    }

    private void FixedUpdate()
    {
        //Get the direction the ball is travelling
        //This is basically the velocity, however we normalize this
        Vector2 direction = m_BallRigidBody2D.velocity.normalized;

        //Ray cast towards the paddle
        RaycastHit2D hit = Physics2D.Raycast(Ball.transform.position, direction, RayDistance, PaddleLayer);

        // Draw a ray we can see in scene view
        Debug. DrawRay(Ball.transform.position, direction * RayDistance, Color.red);

        if (hit)
        {
            PaddleCollider. SetActive(true);

            // Reset our paddle collider so it is flat and at position of paddle
            PaddleCollider.transform.rotation = new Quaternion();
            PaddleCollider.transform.position = transform.position;

            // If we have hit we want to rotate the ball around that point
            Vector2 hitPoint = hit.point; // Worldspace

            // Transform above into local space for the paddle
            // so we can figure how far along paddle hit was
            Vector2 localHitPoint = hitPoint - (Vector2)transform.position;

            // Calculate the offseet on the paddle that we hit
            // this will be -1 to 1, with 0 being centre;
            float offset = /*point.x / length*/ localHitPoint.x / (m_PaddleSpriteRenderer.bounds.extents.x);

            // Get our incoming angle
            // -180' to 180'
            var incomingAngle = Vector2.SignedAngle(direction, Vector3.down);

            // Calculate our angularchange based on hit position
            float adjustedAngularChange = -AngularChange * offset;

            // We want to translate the incoming angle based on the offset
            // but if it's a really shallow angle, bounce it more upwards. 
            // (This is to prevent overly sideways movment)
            // Setting the paddle to half incoming angle will reflect directly up
            // so we use this for our corrective figure
            float correctionForShallowHitsAngle = -incomingAngle / 2;

            // Now we can get a value between to two based on how
            // sideways the ball in coming in from
            // if its 90' then 100% use the correctionForShallowHitsAngle
            // if it's 0' then 100% use the adjustedAngularChange
            // we can use linear interpolation (lerp) for this. 

            float computedAngularChange =
                Mathf. Lerp(adjustedAngularChange, correctionForShallowHitsAngle, Mathf. Abs(incomingAngle) / 90);

            // Rotate around hit point with angle adjusted by above percent
            PaddleCollider.transform. RotateAround(hitPoint, Vector3.forward, computedAngularChange);

        }
        else
        {
            PaddleCollider. SetActive(false);
        }
    }
}

```

