The issue here is with the precedence of Animations in SwiftUI. Because TabView is a struct we are unable to change, its animation detection precedence cannot really be changed. The solution to this, however clunky, is to write our own custom tab view that has the expected behavior.
I apologize for how much code is here, but the behavior you described is surprisingly complex. In essence, we have a TimeLineView that is sending automatic updates to our view, telling it to change the pages, as you would see on Instagram. TimeLineView is a new feature, so if you want this to work old school, you could replace it with a Timer and its onReceive method, but I'm using this for brevity.
In the pages themselves, we are listening for this update, but only actually changing the page to the next one if there is room to do so and we are not long pressing the view. We use the .updating modifier on the LongPressGesture to know exactly when our finger is still on the screen or not. This LongPressGesture is combined in a SimultaneousGesture with a DragGesture, so that the drag can also be activated. In the drag gesture, we wait for the user's mouse/finger to traverse a certain percentage of the screen before animating the change in pages.
When sliding backwards, we initiate an async request to set the animation direction back to sliding forwards once the animation completes, so that updates received from the TimeLineView still animate in the correct direction, no matter which way we just swiped. Using custom gestures here has the added benefit that if you choose to do so, you can implement some fancy geometry effects to more closely emulate Instagram's animations. At the same time, our CustomPageView is still fully interactable, which means I can still click on button1 and see it's onTapGesture print message!
One caveat of passing in Views to a struct as a generic as I am doing in CustomTabView is that all of the views must be of the same type, which is part of the reason the pages are now reusable structs in their own right. If you have any questions about what you can / can't do with this methodology, let me know, but I've just run this in Playground same as you and it works exactly as described.
import SwiftUI
import PlaygroundSupport
// Custom Tab View to handle all the expected behaviors
struct CustomTabView<Page: View>: View {
    @Binding var pageIndex: Int
    var pages: [Page]
    
    /// Primary initializer for a Custom Tab View
    /// - Parameters:
    ///   - pageIndex: The index controlling which page we are viewing
    ///   - pages: The views to display on each Page
    init(_ pageIndex: Binding<Int>, pages: [() -> Page]) {
        self._pageIndex = pageIndex
        self.pages = pages.map { $0() }
    }
    struct currentPage<Page: View>: View {
        @Binding var pageIndex: Int
        @GestureState private var isPressingDown: Bool = false
        @State private var forwards: Bool = true
        private let animationDuration = 0.5
        var pages: [Page]
        var date: Date
        
        /// - Parameters:
        ///   - pageIndex: The index controlling which page we are viewing
        ///   - pages: The views to display on each Page
        ///   - date: The current date
        init(_ pageIndex: Binding<Int>, pages: [Page], date: Date) {
            self._pageIndex = pageIndex
            self.pages = pages
            self.date = date
        }
        
        var body: some View {
            // Ensure that the Page fills the screen
            GeometryReader { bounds in
                ZStack {
                    // You can obviously change this to whatever you like, but it's here right now because SwiftUI will not look for gestures on a clear background, and the CustomPageView I implemented is extremely bare
                    Color.red
                    
                    // Space the Page horizontally to keep it centered
                    HStack {
                        Spacer()
                        pages[pageIndex]
                        Spacer()
                    }
                }
                // Frame this ZStack with the GeometryReader's bounds to include the full width in gesturable bounds
                .frame(width: bounds.size.width, height: bounds.size.height)
                // Identify this page by its index so SwiftUI knows our views are not identical
                .id("page\(pageIndex)")
                // Specify the transition type
                .transition(getTransition())
                .gesture(
                    // Either of these Gestures are allowed
                    SimultaneousGesture(
                        // Case 1, we perform a Long Press
                        LongPressGesture(minimumDuration: 0.1, maximumDistance: .infinity)
                            // Sequence this Gesture before an infinitely long press that will never trigger
                            .sequenced(before: LongPressGesture(minimumDuration: .infinity))
                            // Update the isPressingDown value
                            .updating($isPressingDown) { value, state, _ in
                                switch value {
                                    // This means the first Gesture completed
                                    case .second(true, nil):
                                        // Update the GestureState
                                        state = true
                                    // We don't need to handle any other case
                                    default: break
                                }
                            },
                        // Case 2, we perform a Drag Gesture
                        DragGesture(minimumDistance: 10)
                            .onChanged { onDragChange($0, bounds.size) }
                    )
                )
            }
            // If the user releases their finger, set the slide animation direction back to forwards
            .onChange(of: isPressingDown) { newValue in
                if !newValue { forwards = true }
            }
            // When we receive a signal from the TimeLineView
            .onChange(of: date) { _ in
                // If the animation is not pause and there are still pages left to show
                if !isPressingDown && pageIndex < pages.count - 1{
                    // This should always say sliding forwards, because this will only be triggered automatically
                    print("changing pages by sliding \(forwards ? "forwards" : "backwards")")
                    // Animate the change in pages
                    withAnimation(.easeIn(duration: animationDuration)) {
                        pageIndex += 1
                    }
                }
            }
        }
        
        /// Called when the Drag Gesture occurs
        private func onDragChange(_ drag: DragGesture.Value, _ frame: CGSize) {
            // If we've dragged across at least 15% of the screen, change the Page Index
            if abs(drag.translation.width) / frame.width > 0.15 {
                // If we're moving forwards and there is room
                if drag.translation.width < 0 && pageIndex < pages.count - 1 {
                    forwards = true
                    withAnimation(.easeInOut(duration: animationDuration)) {
                        pageIndex += 1
                    }
                }
                // If we're moving backwards and there is room
                else if drag.translation.width > 0 && pageIndex > 0 {
                    forwards = false
                    withAnimation(.easeInOut(duration: animationDuration)) {
                        pageIndex -= 1
                    }
                    DispatchQueue.main.asyncAfter(deadline: .now() + animationDuration) {
                        forwards = true
                    }
                }
            }
        }
        
        // Tell the view which direction to slide
        private func getTransition() -> AnyTransition {
            // If we are swiping left / moving forwards
            if forwards {
                return .asymmetric(insertion: .move(edge: .trailing), removal: .move(edge: .leading))
            }
            // If we are swiping right / moving backwards
            else {
                return .asymmetric(insertion: .move(edge: .leading), removal: .move(edge: .trailing))
            }
        }
    }
    
    var body: some View {
        ZStack {
            // Create a TimeLine that updates every five seconds automatically
            TimelineView(.periodic(from: Date(), by: 5)) { timeLine in
                // Create a current page struct, as we cant react to timeLine.date changes in this view
                currentPage($pageIndex, pages: pages, date: timeLine.date)
            }
        }
    }
}
// This is the view that becomes the Page in our Custom Tab View, you can make it whatever you want as long as it is reusable
struct CustomPageView: View {
    var title: String
    var buttonTitle: String
    var buttonAction: () -> ()
    
    var body: some View {
        VStack {
            Text("\(title)")
            Button(action: { buttonAction() }, label: { Text("\(buttonTitle)") })
        }
    }
}
struct ContentView: View {
    @State var currentSlideIndex: Int = 0
    @GestureState var isPaused: Bool = false
    
    var body: some View {
        CustomTabView($currentSlideIndex, pages: [
            {
                CustomPageView(title: "slide 1", buttonTitle: "button 1", buttonAction: { print("slide 1 button tapped") })
                
            },
            {
                CustomPageView(title: "slide 2", buttonTitle: "button 2", buttonAction: { print("slide 2 button tapped") })
            }]
        )
        .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
        .frame(width: 400, height: 700, alignment: .bottom)
    }
}
PlaygroundPage.current.setLiveView(ContentView())